package com.ys.filelib.filedialog;

import android.content.Context;
import android.util.SparseArray;

import com.ys.filelib.R;
import com.ys.filelib.filedialog.ftp.FTPDriveHelper;
import com.ys.filelib.filedialog.ftp.FTPHelper;
import com.ys.filelib.filedialog.ftp.FTPService;
import com.ys.filelib.filedialog.loader.RemoteDiskDao;
import com.ys.filelib.filedialog.util.MyLog;

import java.io.File;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Set;

import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.core.Observer;
import io.reactivex.rxjava3.schedulers.Schedulers;


//对数据的操作
public class FileDataModel {

    private final Context context;

    public FileDataModel(Context context) {
        this.context = context;
    }

    public void getLocalStorageList(Callback<SparseArray<List<StorageItem>>> callback) {
        Observable.fromCallable(this::getStorageArray)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(callback);
    }

    private SparseArray<List<StorageItem>> getStorageArray() {
        StorageItem item = null;
        List<StorageItem> allList = new ArrayList<>();
        List<StorageItem> usbList = new ArrayList<>();
        List<StorageItem> localList = new ArrayList<>();
        List<StorageItem> cloudList = new ArrayList<>();
        List<StorageItem> ftpList = new ArrayList<>();
        List<String> listPath = StorageUtils.getAllExternalStorage();
        for (String path : listPath) {
            if (StorageUtils.isLocalStorage(path)) {
                item = getStorageItemByPath(path);
                item.check = true;
                localList.add(item);
                continue;
            }
            item = getStorageItemByPath(path);
            usbList.add(item);
        }
        cloudList.add(getCloudStorageItem());
        loadRemoteDiskList(ftpList);
        allList.addAll(localList);
        allList.addAll(usbList);
        allList.addAll(cloudList);
        allList.addAll(ftpList);
        SparseArray<List<StorageItem>> array = new SparseArray<>();
        array.put(StorageItem.TYPE_USB, usbList);
        array.put(StorageItem.TYPE_INNER, localList);
        array.put(StorageItem.TYPE_CLOUD, cloudList);
        array.put(StorageItem.TYPE_FTP, ftpList);
        array.put(StorageItem.TYPE_ALL, allList);
        return array;
    }

    public StorageItem getStorageItemByPath(String path) {
        if (StorageUtils.isLocalStorage(path)) {
            return new StorageItem(context.getString(R.string.str_local), StorageItem.TYPE_INNER, R.drawable.ic_local, R.drawable.ic_local_check, false, path);
        }
        String name = StorageUtils.getPathDescribe(path);
        return new StorageItem(name, StorageItem.TYPE_USB, R.drawable.ic_usb, R.drawable.ic_usb_check, false, path);
    }

    public StorageItem getCloudStorageItem() {
        String path = StorageUtils.getLocalRootPath() + "/Android/CloudDisk";
        String name = context.getString(R.string.str_cloud);
        return new StorageItem(name, StorageItem.TYPE_CLOUD, R.drawable.ic_cloud, R.drawable.ic_cloud_check, false, path);
    }

    /**
     * DriveUser转StorageItem
     */
    public static StorageItem driveUserToStorageItem(RemoteDiskDao.DriveUser user) {
        StorageItem item = new StorageItem(user.name, user.driveType, R.drawable.ic_ftp, R.drawable.ic_ftp, false, user.path);
        item.name = user.ip + ":" + user.port;
        item.host = user.ip;
        item.port = user.port;
        item.email = user.email;
        item.username = user.name;
        return item;
    }

    /**
     * 加载远程云端硬盘列表
     */
    private void loadRemoteDiskList(List<StorageItem> cloudList) {
        List<RemoteDiskDao.DriveUser> list = RemoteDiskDao.getDriveList(context, RemoteDiskDao.TYPE_FTP);
        for (RemoteDiskDao.DriveUser user : list) {
            cloudList.add(driveUserToStorageItem(user));
            FTPService.setFTPHelper(FTPHelper.create(user.ip, user.port, user.name, user.password));
        }
    }

    public void listDirFile(String dir, int fileType, Observer<List<FileInfo>> callback) {
        Observable.fromCallable(() -> {
                    if (dir.startsWith(FileUtil.sLocalRoot)) {
                        String[] filter = new String[]{FileUtil.sLocalRoot + "/Android", FileUtil.sLocalRoot + "/."};
                        return getFilesByType(new File(dir), fileType, filter);
                    }
                    return getFilesByType(new File(dir), fileType);
                }).subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(callback);
    }

    public void listDirFile(String dir, StorageItem item, Set<Integer> types, Observer<List<FileInfo>> callback) {
        if (dir == null) {
            return;
        }
        Observable.fromCallable(() -> {
                    List<FileInfo> list;
                    if (item.type == StorageItem.TYPE_FTP) {
                        list = listFTP(dir, item.host, item.port, item.username, types);
                    } else {
                        list = new ArrayList<>();
                        File file = new File(dir);
                        String[] names = file.list();
                        if (names == null || names.length < 1) {
                            return list;
                        }
                        for (String name : names) {
                            list.add(new FileInfo(new File(dir, name)));
                        }
                        FileUtil.filterFiles(list, types);
                    }
                    FileSort.sort(list, FileSort.SORT_BY_NAME_ASC);
                    return list;
                }).subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(callback);
    }

    /**
     * 根据目录dir显示FTP文件列表
     * @param dir 文件目录
     * @param host 主机名
     * @param port 端口
     * @param username 用户名
     * @param types 需要的文件类型
     */
    private List<FileInfo> listFTP(String dir, String host, int port, String username, Set<Integer> types) {
        FTPDriveHelper helper = FTPService.getFTPHelper(host, port, username);
        List<FileInfo> list = helper.listFiles(dir);
        FileUtil.filterFiles(list, types);
        return list;
    }

    /**
     * @param file   文件
     * @param type
     * @param filter 需要过滤的文件路径
     * @return list
     */
    private List<FileInfo> getFilesByType(File file, int type, String... filter) {
        List<FileInfo> list = new ArrayList<>();
        if (!file.exists()) {
            return list;
        }
        if (file.isDirectory()) {
            return getTypeFileByDirectory(file, type, filter);
        }
        file = getFileByType(file, type);
        if (file != null) {
            list.add(new FileInfo(file));
        }
        return list;
    }

    /**
     * @param type
     * @param directory 目录
     * @return list
     */
    private List<FileInfo> getTypeFileByDirectory(File directory, int type, String... filter) {
        List<FileInfo> data = new ArrayList<>();
        Queue<File> queue = new LinkedList<>();
        listDirFile(directory, queue, filter);
        File file;
        while (!queue.isEmpty()) {
            file = queue.poll();
            if (file == null) {
                continue;
            }
            if (file.isDirectory()) {
                listDirFile(file, queue, filter);
                continue;
            }
            file = getFileByType(file, type);
            if (file != null) {
                data.add(new FileInfo(file));
            }
        }
        return data;
    }

    private void listDirFile(File directory, Queue<File> queue, String... filter) {
        if (directory.isDirectory()) {
            if (filter.length > 0) {
                for (String path : filter) {
                    if (directory.getAbsolutePath().startsWith(path)) {
                        return;
                    }
                }
            }
            File[] files = directory.listFiles();
            if (files == null) {
                return;
            }
            for (File file : files) {
                queue.offer(file);
            }
        }
    }

    /**
     * @param file 文件
     * @param type
     * @return type file
     */
    private File getFileByType(File file, int type) {
        if (file == null || !file.exists()) {
            return null;
        }
        if (type == FileType.FILE_ALL) {
            return file;
        }
        if (file.isDirectory()) {
            return null;
        }
        switch (type) {
            case FileType.FILE_IMAGE:
                if (FileUtil.isImageFile(file.getName())) {
                    return file;
                }
                if (FileUtil.isGifFile(file.getName())) {
                    return file;
                }
                break;
            case FileType.FILE_AUDIO:
                if (FileUtil.isAudioFile(file.getName())) {
                    return file;
                }
                break;
            case FileType.FILE_VIDEO:
                if (FileUtil.isVideoFile(file.getName())) {
                    return file;
                }
                break;
            case FileType.FILE_WHITEBOARD:
                if (FileUtil.isWBD(file.getName())) {
                    return file;
                }
                break;
            case FileType.FILE_OFFICE:
                if (FileUtil.isOffice(file.getName())) {
                    return file;
                }
                break;
        }
        return null;
    }

}
